<template>
  <div class="data-visualization">
    <div class="viz-header">
      <h2>{{ $t('visualization.title') }}</h2>
      <div class="data-info" v-if="currentDataset">
        <span class="info-label">{{ $t('visualization.database') }}:</span> {{ currentDataset.database }}
        <span class="info-separator">|</span>
        <span class="info-label">{{ $t('visualization.measurement') }}:</span> {{ currentDataset.measurement }}
        <span class="info-separator">|</span>
        <span class="info-label">{{ $t('visualization.records') }}:</span> {{ currentDataset.data ? currentDataset.data.length : 0 }}
      </div>
      <div class="viz-controls">
        <el-select v-model="chartType" :placeholder="$t('visualization.chartType')" @change="updateChart">
          <el-option :label="$t('visualization.lineChart')" value="line" />
          <el-option :label="$t('visualization.barChart')" value="bar" />
          <el-option :label="$t('visualization.areaChart')" value="area" />
          <el-option :label="$t('visualization.scatterPlot')" value="scatter" />
        </el-select>
        
        <el-button icon="el-icon-refresh" @click="refreshChart">{{ $t('common.refresh') }}</el-button>
        <el-button icon="el-icon-download" @click="exportChart">{{ $t('visualization.exportImage') }}</el-button>
      </div>
    </div>
    
    <div class="viz-config">
      <el-form :inline="true" :model="chartConfig" size="small">
        <el-form-item :label="$t('visualization.chartTitle')">
          <el-input v-model="chartConfig.title" @change="updateChart" />
        </el-form-item>
        
        <el-form-item :label="$t('visualization.xAxis')">
          <el-select v-model="chartConfig.xAxis" @change="updateChart">
            <el-option
              v-for="col in availableColumns"
              :key="col"
              :label="col"
              :value="col"
            />
          </el-select>
        </el-form-item>
        
        <el-form-item :label="$t('visualization.yAxis')">
          <el-select v-model="chartConfig.yAxis" @change="updateChart">
            <el-option
              v-for="col in availableColumns"
              :key="col"
              :label="col"
              :value="col"
            />
          </el-select>
        </el-form-item>
        
        <el-form-item :label="$t('visualization.groupBy')">
          <el-select v-model="chartConfig.groupBy" clearable @change="updateChart">
            <el-option
              v-for="col in availableColumns"
              :key="col"
              :label="col"
              :value="col"
            />
          </el-select>
        </el-form-item>
      </el-form>
    </div>
    
    <div class="chart-container" ref="chartContainer">
      <div v-if="!hasData" class="no-data">
        <el-empty :description="$t('visualization.noDataToVisualize')" />
      </div>
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import * as echarts from 'echarts'
import i18nMixin from '@/mixins/i18nMixin'

export default {
  name: 'DataVisualization',
  mixins: [i18nMixin],
  
  data() {
    return {
      chart: null,
      chartType: 'line',
      chartConfig: {
        title: 'Query Results',
        xAxis: '',
        yAxis: '',
        groupBy: ''
      }
    }
  },
  
  computed: {
    ...mapState(['queryResults']),
    
    hasData() {
      return this.queryResults && this.queryResults.length > 0 && this.queryResults[0].data && this.queryResults[0].data.length > 0
    },
    
    currentDataset() {
      if (!this.queryResults || this.queryResults.length === 0) return null
      return this.queryResults[0]
    },
    
    currentData() {
      if (!this.currentDataset || !this.currentDataset.data) return []
      return this.currentDataset.data
    },
    
    availableColumns() {
      if (!this.currentData || this.currentData.length === 0) return []
      return Object.keys(this.currentData[0])
    }
  },
  
  mounted() {
    if (!this.hasData) {
      this.$message.warning('No query results to visualize')
      return
    }
    
    this.initChart()
    this.autoDetectAxes()
    this.updateChart()
    
    window.addEventListener('resize', this.handleResize)
  },
  
  beforeDestroy() {
    if (this.chart) {
      this.chart.dispose()
    }
    window.removeEventListener('resize', this.handleResize)
  },
  
  methods: {
    initChart() {
      if (this.$refs.chartContainer) {
        this.chart = echarts.init(this.$refs.chartContainer)
      }
    },
    
    autoDetectAxes() {
      if (this.availableColumns.length >= 2) {
        const timeColumn = this.availableColumns.find(col => 
          col.toLowerCase().includes('time') || col === '_time' || col === 'time'
        )
        
        // Find numeric columns for Y axis
        const numericColumns = this.availableColumns.filter(col => {
          if (col === timeColumn) return false
          const firstValue = this.currentData[0][col]
          return typeof firstValue === 'number' || !isNaN(parseFloat(firstValue))
        })
        
        this.chartConfig.xAxis = timeColumn || this.availableColumns[0]
        this.chartConfig.yAxis = numericColumns[0] || this.availableColumns[1]
        
        // Set meaningful title
        if (this.currentDataset) {
          this.chartConfig.title = `${this.currentDataset.measurement} - ${this.chartConfig.yAxis}`
        }
      }
    },
    
    updateChart() {
      if (!this.chart || !this.hasData) return
      
      const option = this.generateChartOption()
      this.chart.setOption(option, true)
    },
    
    generateChartOption() {
      const { xAxis, yAxis, groupBy, title } = this.chartConfig

      if (!xAxis || !yAxis) {
        return {
          title: { text: 'Please select X and Y axes' },
          xAxis: {},
          yAxis: {},
          series: []
        }
      }

      let series = []
      const isXAxisTime = this.isTimeColumn(xAxis)

      if (groupBy) {
        const groups = this.groupData(groupBy)
        series = Object.keys(groups).map(group => ({
          name: group,
          type: this.chartType === 'area' ? 'line' : this.chartType,
          areaStyle: this.chartType === 'area' ? {} : null,
          data: groups[group].map(item => {
            const xVal = this.formatValue(item[xAxis], xAxis)
            const yVal = this.formatValue(item[yAxis], yAxis)
            // 保存原始时间值用于 tooltip 显示纳秒
            return {
              value: [xVal, yVal],
              rawTime: item[xAxis] // 保存原始时间
            }
          })
        }))
      } else {
        series = [{
          name: yAxis,
          type: this.chartType === 'area' ? 'line' : this.chartType,
          areaStyle: this.chartType === 'area' ? {} : null,
          data: this.currentData.map(item => {
            const xVal = this.formatValue(item[xAxis], xAxis)
            const yVal = this.formatValue(item[yAxis], yAxis)
            // 保存原始时间值用于 tooltip 显示纳秒
            return {
              value: [xVal, yVal],
              rawTime: item[xAxis] // 保存原始时间
            }
          })
        }]
      }

      return {
        title: {
          text: title,
          left: 'center'
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'cross'
          },
          formatter: (params) => {
            if (!params || params.length === 0) return ''

            let result = ''

            // 显示 X 轴值（时间）
            const firstParam = params[0]
            if (isXAxisTime && firstParam.data && firstParam.data.rawTime) {
              // 显示纳秒精度的时间
              result += `<div style="font-weight: bold; margin-bottom: 5px;">${this.formatTimeForDisplay(firstParam.data.rawTime)}</div>`
            } else {
              result += `<div style="font-weight: bold; margin-bottom: 5px;">${xAxis}: ${firstParam.axisValue}</div>`
            }

            // 显示每个系列的值
            params.forEach(param => {
              const marker = param.marker
              const seriesName = param.seriesName
              const value = param.data.value[1]
              result += `<div>${marker} ${seriesName}: ${value}</div>`
            })

            return result
          }
        },
        legend: {
          bottom: 10,
          data: series.map(s => s.name)
        },
        grid: {
          left: '3%',
          right: '4%',
          bottom: '15%',
          containLabel: true
        },
        xAxis: {
          type: isXAxisTime ? 'time' : 'category',
          name: xAxis,
          nameLocation: 'middle',
          nameGap: 30,
          axisLabel: isXAxisTime ? {
            formatter: (value) => {
              // 时间轴标签格式化（简化显示）
              const date = new Date(value)
              const month = String(date.getMonth() + 1).padStart(2, '0')
              const day = String(date.getDate()).padStart(2, '0')
              const hours = String(date.getHours()).padStart(2, '0')
              const minutes = String(date.getMinutes()).padStart(2, '0')
              const seconds = String(date.getSeconds()).padStart(2, '0')
              return `${month}-${day}\n${hours}:${minutes}:${seconds}`
            }
          } : {}
        },
        yAxis: {
          type: 'value',
          name: yAxis,
          nameLocation: 'middle',
          nameGap: 40
        },
        series,
        toolbox: {
          show: true,
          orient: 'horizontal',
          right: 20,
          top: 20,
          feature: {
          }
        },
        dataZoom: [{
          type: 'inside',
          start: 0,
          end: 100
        }, {
          start: 0,
          end: 100,
          handleIcon: 'M10.7,11.9v-1.3H9.3v1.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4v1.3h1.3v-1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z',
          handleSize: '80%',
          handleStyle: {
            color: '#fff',
            shadowBlur: 3,
            shadowColor: 'rgba(0, 0, 0, 0.6)',
            shadowOffsetX: 2,
            shadowOffsetY: 2
          }
        }]
      }
    },
    
    groupData(groupBy) {
      const groups = {}
      
      this.currentData.forEach(item => {
        const key = item[groupBy]
        if (!groups[key]) {
          groups[key] = []
        }
        groups[key].push(item)
      })
      
      return groups
    },
    
    formatValue(value, columnName) {
      if (value === null || value === undefined) return null

      // Handle time columns
      if (this.isTimeColumn(columnName)) {
        // For time axis in ECharts, convert to JavaScript Date object
        return this.parseTimeToDate(value)
      }

      // Handle numeric values
      if (typeof value === 'number') return value
      if (!isNaN(parseFloat(value))) return parseFloat(value)

      return value
    },

    parseTimeToDate(time) {
      if (!time) return null

      let timeStr = String(time)

      // RFC3339 格式: "2024-01-01T12:00:00.123456789Z"
      if (timeStr.includes('T') && timeStr.includes('Z')) {
        // JavaScript Date 只支持毫秒，但我们保存完整字符串用于 tooltip
        return new Date(timeStr)
      }

      // 纳秒时间戳（19位数字）
      if (/^\d{19}$/.test(timeStr)) {
        const nanoseconds = BigInt(timeStr)
        const milliseconds = Number(nanoseconds / 1000000n)
        return new Date(milliseconds)
      }

      // 微秒时间戳（16位数字）
      if (/^\d{16}$/.test(timeStr)) {
        const microseconds = BigInt(timeStr)
        const milliseconds = Number(microseconds / 1000n)
        return new Date(milliseconds)
      }

      // 默认使用 Date 解析
      const date = new Date(time)
      return isNaN(date.getTime()) ? null : date
    },

    formatTimeForDisplay(time) {
      if (!time) return ''

      // InfluxDB 时间格式可能是：
      // 1. RFC3339 字符串: "2024-01-01T12:00:00.123456789Z"
      // 2. 纳秒时间戳: 1704110400123456789
      // 3. 微秒时间戳: 1704110400123456

      let timeStr = String(time)

      // 如果是 RFC3339 格式（包含纳秒），直接格式化
      if (timeStr.includes('T') && timeStr.includes('Z')) {
        const match = timeStr.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})\.?(\d*)Z?$/)
        if (match) {
          const [, datetime, nanos] = match
          const date = new Date(datetime + 'Z')

          const year = date.getFullYear()
          const month = String(date.getMonth() + 1).padStart(2, '0')
          const day = String(date.getDate()).padStart(2, '0')
          const hours = String(date.getHours()).padStart(2, '0')
          const minutes = String(date.getMinutes()).padStart(2, '0')
          const seconds = String(date.getSeconds()).padStart(2, '0')
          const nanoseconds = nanos ? nanos.padEnd(9, '0') : '000000000'

          return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${nanoseconds}`
        }
      }

      // 如果是纳秒时间戳（19位数字）
      if (/^\d{19}$/.test(timeStr)) {
        const nanoseconds = BigInt(timeStr)
        const milliseconds = Number(nanoseconds / 1000000n)
        const nanos = String(nanoseconds % 1000000n).padStart(6, '0') + '000'

        const date = new Date(milliseconds)
        const year = date.getFullYear()
        const month = String(date.getMonth() + 1).padStart(2, '0')
        const day = String(date.getDate()).padStart(2, '0')
        const hours = String(date.getHours()).padStart(2, '0')
        const minutes = String(date.getMinutes()).padStart(2, '0')
        const seconds = String(date.getSeconds()).padStart(2, '0')
        const ms = String(date.getMilliseconds()).padStart(3, '0')

        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}${nanos.slice(3)}`
      }

      // 如果是微秒时间戳（16位数字）
      if (/^\d{16}$/.test(timeStr)) {
        const microseconds = BigInt(timeStr)
        const milliseconds = Number(microseconds / 1000n)
        const micros = String(microseconds % 1000n).padStart(3, '0')

        const date = new Date(milliseconds)
        const year = date.getFullYear()
        const month = String(date.getMonth() + 1).padStart(2, '0')
        const day = String(date.getDate()).padStart(2, '0')
        const hours = String(date.getHours()).padStart(2, '0')
        const minutes = String(date.getMinutes()).padStart(2, '0')
        const seconds = String(date.getSeconds()).padStart(2, '0')
        const ms = String(date.getMilliseconds()).padStart(3, '0')

        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}${micros}000`
      }

      // 默认使用 Date 解析（毫秒精度）
      const date = new Date(time)
      if (isNaN(date.getTime())) {
        return String(time)
      }

      const year = date.getFullYear()
      const month = String(date.getMonth() + 1).padStart(2, '0')
      const day = String(date.getDate()).padStart(2, '0')
      const hours = String(date.getHours()).padStart(2, '0')
      const minutes = String(date.getMinutes()).padStart(2, '0')
      const seconds = String(date.getSeconds()).padStart(2, '0')
      const ms = String(date.getMilliseconds()).padStart(3, '0')

      return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${ms}000000`
    },
    
    isTimeColumn(column) {
      return column.toLowerCase().includes('time') || column === '_time'
    },
    
    refreshChart() {
      this.updateChart()
      this.$message.success('Chart refreshed')
    },
    
    exportChart() {
      if (!this.chart) return
      
      const url = this.chart.getDataURL({
        type: 'png',
        pixelRatio: 2,
        backgroundColor: '#fff'
      })
      
      const link = document.createElement('a')
      link.download = `chart_${Date.now()}.png`
      link.href = url
      link.click()
      
      this.$message.success('Chart exported as image')
    },
    
    handleResize() {
      if (this.chart) {
        this.chart.resize()
      }
    }
  }
}
</script>

<style scoped>
.data-visualization {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 30px;
  overflow: hidden;
  background: linear-gradient(135deg, #f5f7fa 0%, #e9ecef 100%);
}

.viz-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
  padding-bottom: 20px;
  border-bottom: 2px solid #e2e8f0;
  flex-wrap: wrap;
  gap: 15px;
}

.viz-header h2 {
  margin: 0;
  font-size: 28px;
  font-weight: 700;
  color: #1e293b;
  letter-spacing: -0.5px;
}

.data-info {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #64748b;
  background: white;
  padding: 8px 16px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.info-label {
  font-weight: 600;
  color: #475569;
}

.info-separator {
  color: #cbd5e1;
}

.viz-controls {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.viz-controls .el-select {
  min-width: 140px;
}

.viz-controls .el-button {
  background: white;
  border-color: #e2e8f0;
  color: #475569;
  font-weight: 500;
}

.viz-controls .el-button:hover {
  background: #3b82f6;
  border-color: #3b82f6;
  color: white;
}

.viz-config {
  background: white;
  padding: 20px;
  border-radius: 12px;
  margin-bottom: 24px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.viz-config .el-form-item {
  margin-bottom: 0;
  margin-right: 20px;
}

.viz-config .el-form-item__label {
  font-weight: 500;
  color: #475569;
}

.chart-container {
  flex: 1;
  background: white;
  border-radius: 12px;
  padding: 24px;
  min-height: 400px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  position: relative;
}

.no-data {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.no-data .el-empty__description {
  color: #64748b;
  font-size: 14px;
}

@media (max-width: 1200px) {
  .viz-header {
    flex-direction: column;
    align-items: flex-start;
  }
  
  .data-info {
    width: 100%;
    justify-content: center;
  }
  
  .viz-controls {
    width: 100%;
    justify-content: flex-end;
  }
}

@media (max-width: 768px) {
  .data-visualization {
    padding: 20px;
  }
  
  .viz-config .el-form {
    display: flex;
    flex-direction: column;
  }
  
  .viz-config .el-form-item {
    width: 100%;
    margin-bottom: 10px;
  }
  
  .viz-controls {
    flex-direction: column;
  }
  
  .viz-controls .el-select,
  .viz-controls .el-button {
    width: 100%;
  }
}
</style>